package ru.vba.strategy.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import ru.vba.context.FieldContext;
import ru.vba.context.GameContext;
import ru.vba.exceptions.GameException;
import ru.vba.pojo.Cell;
import ru.vba.pojo.Coordinate;
import ru.vba.pojo.Field;
import ru.vba.pojo.Player;
import ru.vba.pojo.Point;
import ru.vba.strategy.EndTurnNotifier;
import ru.vba.utils.ValidatorUtils;
import ru.vba.validator.FieldValidator;
import ru.vba.validator.WordValidator;

public class GameStrategyImpl extends AbstractGameStrategy {
	private final static int PLAYER_POINTS = 7;

	public GameStrategyImpl(GameContext context) {
		super(context);
	}

	public synchronized List<Cell> putWord(Map<Coordinate, Point> word)
			throws GameException {
		ValidatorUtils.validate(
				Arrays.asList(new WordValidator(), new FieldValidator()),
				context, word);
		List<Cell> result = context.getField().putWord(word);
		int point = 0;
		for (Cell cell : result){
			point += (cell.getPoint().getScore() * cell.getBonus().getFactor());
		}

		getCurrentPlayer().upScore(point);
		getCurrentPlayer().upWord(result);
		return result;
	}

	public void endTurn() throws GameException {
		context.charge();
		context.nextPlayer(new EndTurnNotifier() {
			public void endTurn() throws GameException {
				context.nextPlayer(this);
			}
		});
	}

	public List<Point> changePoints(List<Point> points)
			throws GameException {
		List<Point> result = new ArrayList<Point>();
		FieldContext field = context.getField();
		for (Point point : points) {
			getCurrentPlayer().getPoints().remove(point);
			result.add(field.getRandomPoint());
			field.addHeap(point);
		}
		return result;
	}

	public Field getField() {
		return null;
	}

	public synchronized Player getCurrentPlayer() throws GameException {
		return context.getCurrentPlayer();
	}

	public void startGame() throws GameException {
		for (Player player : context.getPlayers()) {
			List<Point> points = new ArrayList<Point>();
			for (int i = 0; i < PLAYER_POINTS; i++) {
				Point point = context.getField().getRandomPoint();
				points.add(point);
			}
			player.setPoints(points);
		}
		context.start();
		endTurn();
	}

}
